home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / util / net.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  34KB  |  1,243 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. import sys
  6. import traceback
  7. import re
  8. import struct
  9. import logging
  10. import socks
  11. import socket
  12. import asynchat
  13. import urllib
  14. import urllib2
  15. import urlparse
  16. import httplib
  17. import httplib2
  18. import cookielib
  19. from httplib import HTTPConnection
  20. from httplib import NotConnected
  21. import primitives
  22. import proxy_settings
  23. from Events import EventMixin
  24. from callbacks import callsback
  25. log = logging.getLogger('util.net')
  26. default_chunksize = 4096
  27.  
  28. def get_ips_s(hostname = ''):
  29.     if not hostname:
  30.         pass
  31.     return socket.gethostbyname_ex(socket.gethostname())[2]
  32.  
  33.  
  34. def get_ips(hostname = ''):
  35.     return [ socket.inet_aton(ip) for ip in get_ips_s(hostname) ]
  36.  
  37. myips = get_ips
  38.  
  39. def myip():
  40.     return myips()[0]
  41.  
  42.  
  43. def ip_from_bytes(bytes):
  44.     return socket.inet_ntoa(bytes)
  45.  
  46.  
  47. class FileChunker:
  48.     
  49.     def __init__(self, fileobj, chunksize = default_chunksize, close_when_done = False, progress_cb = (lambda bytes: pass), bytecounter = None):
  50.         self.fileobj = fileobj
  51.         self.chunksize = chunksize
  52.         self.close_when_done = close_when_done
  53.         if bytecounter is None:
  54.             bytecounter = fileobj.tell
  55.         
  56.         self.total = bytecounter()
  57.         self.progress_cb = progress_cb
  58.         self.cancelled = False
  59.  
  60.     
  61.     def more(self):
  62.         
  63.         try:
  64.             data_read = self.fileobj.read(self.chunksize)
  65.         except ValueError:
  66.             
  67.             try:
  68.                 self.fileobj.close()
  69.             except:
  70.                 pass
  71.  
  72.             return ''
  73.  
  74.         sz = len(data_read)
  75.         if sz == 0 and self.close_when_done:
  76.             self.fileobj.close()
  77.         
  78.         self.total += sz
  79.         self.progress_cb(self.total)
  80.         return data_read
  81.  
  82.     
  83.     def tofile(cls, sourcefile, outfile, progress_callback = (lambda : pass), bytecounter = None):
  84.         gen = cls.tofile_gen(sourcefile, outfile, progress_callback, bytecounter)
  85.         gen.next()
  86.         
  87.         try:
  88.             gen.next()
  89.         except StopIteration:
  90.             pass
  91.  
  92.  
  93.     tofile = classmethod(tofile)
  94.     
  95.     def tofile_gen(cls, sourcefile, outfile, progress_callback = (lambda : pass), bytecounter = None):
  96.         fc = cls(sourcefile, close_when_done = True, bytecounter = bytecounter)
  97.         yield fc
  98.         chunk = fc.more()
  99.         bytes_written = 0
  100.         write = outfile.write
  101.         tell = outfile.tell
  102.         more = fc.more
  103.         while chunk and not (fc.cancelled):
  104.             write(chunk)
  105.             bytes_written += len(chunk)
  106.             progress_callback(tell())
  107.             chunk = more()
  108.         outfile.close()
  109.  
  110.     tofile_gen = classmethod(tofile_gen)
  111.  
  112.  
  113. def httpjoin(base, path, keepquery = False):
  114.     if path.startswith('http'):
  115.         return path
  116.     else:
  117.         joined = urlparse.urljoin(base, path)
  118.         if not keepquery:
  119.             parsed = list(urlparse.urlparse(joined))
  120.             parsed[4] = ''
  121.             return urlparse.urlunparse(parsed)
  122.         else:
  123.             return joined
  124.  
  125.  
  126. class UrlQuery(str):
  127.     
  128.     def parse(cls, url, parse_query = True):
  129.         (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
  130.         if parse_query:
  131.             querymap = { }
  132.             for elem in query.split('&'):
  133.                 (key, value) = None if '=' in elem else (elem, True)
  134.                 querymap[key] = value
  135.             
  136.             query = querymap
  137.         
  138.         return dict(scheme = scheme, netloc = netloc, path = path, params = params, query = query, fragment = fragment)
  139.  
  140.     parse = classmethod(parse)
  141.     
  142.     def __new__(cls, link, d = { }, **kwargs):
  143.         if link.endswith('?'):
  144.             link = link[:-1]
  145.         
  146.         if '?' in link:
  147.             joiner = '&'
  148.         else:
  149.             joiner = '?'
  150.         return str.__new__(cls, ''.join([
  151.             link,
  152.             joiner,
  153.             WebFormData(d = d, **kwargs)]))
  154.  
  155.  
  156.  
  157. class WebFormData(str):
  158.     
  159.     def __new__(cls, d = { }, **kwargs):
  160.         kwargs = None if d and kwargs else d
  161.         base = urllib.urlencode(kwargs)
  162.         return str.__new__(cls, base)
  163.  
  164.  
  165.  
  166. def int_to_ip(s, byteorder = '<'):
  167.     return '.'.join((lambda .0: for c in .0:
  168. str(ord(c)))(struct.pack(byteorder + 'I', int(s))))
  169.  
  170. spacify_pattern = re.compile('( {2,})')
  171.  
  172. def spacify_repl(m):
  173.     l = len(m.group())
  174.     if l == 2:
  175.         return '  '
  176.     else:
  177.         return ' ' + ''.join([
  178.             ' '] * (l - 2)) + ' '
  179.  
  180.  
  181. def spacify(s):
  182.     return spacify_pattern.sub(spacify_repl, s)
  183.  
  184. urlregex = re.compile("([A-Za-z][A-Za-z0-9+.-]{1,120}:[A-Za-z0-9/](([A-Za-z0-9$_.+!*,;/?:@&~=-])|%[A-Fa-f0-9]{2}){1,333}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*,;/?:@&~=%-']{0,1000}))?)[^\\. <]")
  185. TLDs = [
  186.     'arpa',
  187.     'root',
  188.     'aero',
  189.     'asia',
  190.     'biz',
  191.     'com',
  192.     'coop',
  193.     'edu',
  194.     'gov',
  195.     'info',
  196.     'int',
  197.     'museum',
  198.     'name',
  199.     'net',
  200.     'org',
  201.     'pro',
  202.     'ac',
  203.     'ad',
  204.     'ae',
  205.     'af',
  206.     'ag',
  207.     'ai',
  208.     'al',
  209.     'am',
  210.     'an',
  211.     'ao',
  212.     'aq',
  213.     'ar',
  214.     'as',
  215.     'at',
  216.     'au',
  217.     'aw',
  218.     'ax',
  219.     'az',
  220.     'ba',
  221.     'bb',
  222.     'bd',
  223.     'be',
  224.     'bf',
  225.     'bg',
  226.     'bh',
  227.     'bi',
  228.     'bj',
  229.     'bm',
  230.     'bn',
  231.     'bo',
  232.     'br',
  233.     'bs',
  234.     'bt',
  235.     'bv',
  236.     'bw',
  237.     'by',
  238.     'bz',
  239.     'ca',
  240.     'cc',
  241.     'cd',
  242.     'cf',
  243.     'cg',
  244.     'ch',
  245.     'ci',
  246.     'ck',
  247.     'cl',
  248.     'cm',
  249.     'cn',
  250.     'co',
  251.     'cr',
  252.     'cu',
  253.     'cv',
  254.     'cx',
  255.     'cy',
  256.     'cz',
  257.     'de',
  258.     'dj',
  259.     'dk',
  260.     'dm',
  261.     'do',
  262.     'dz',
  263.     'ec',
  264.     'ee',
  265.     'eg',
  266.     'er',
  267.     'es',
  268.     'et',
  269.     'eu',
  270.     'fi',
  271.     'fj',
  272.     'fk',
  273.     'fm',
  274.     'fo',
  275.     'fr',
  276.     'ga',
  277.     'gb',
  278.     'gd',
  279.     'ge',
  280.     'gf',
  281.     'gg',
  282.     'gh',
  283.     'gi',
  284.     'gl',
  285.     'gm',
  286.     'gn',
  287.     'gp',
  288.     'gq',
  289.     'gr',
  290.     'gs',
  291.     'gt',
  292.     'gu',
  293.     'gw',
  294.     'gy',
  295.     'hk',
  296.     'hm',
  297.     'hn',
  298.     'hr',
  299.     'ht',
  300.     'hu',
  301.     'id',
  302.     'ie',
  303.     'il',
  304.     'im',
  305.     'in',
  306.     'io',
  307.     'iq',
  308.     'ir',
  309.     'is',
  310.     'it',
  311.     'je',
  312.     'jm',
  313.     'jo',
  314.     'jp',
  315.     'ke',
  316.     'kg',
  317.     'kh',
  318.     'ki',
  319.     'km',
  320.     'kn',
  321.     'kp',
  322.     'kr',
  323.     'kw',
  324.     'ky',
  325.     'kz',
  326.     'la',
  327.     'lb',
  328.     'lc',
  329.     'li',
  330.     'lk',
  331.     'lr',
  332.     'ls',
  333.     'lt',
  334.     'lu',
  335.     'lv',
  336.     'ly',
  337.     'ma',
  338.     'mc',
  339.     'md',
  340.     'me',
  341.     'mg',
  342.     'mh',
  343.     'mk',
  344.     'ml',
  345.     'mm',
  346.     'mn',
  347.     'mo',
  348.     'mp',
  349.     'mq',
  350.     'mr',
  351.     'ms',
  352.     'mt',
  353.     'mu',
  354.     'mv',
  355.     'mw',
  356.     'mx',
  357.     'my',
  358.     'mz',
  359.     'na',
  360.     'nc',
  361.     'ne',
  362.     'nf',
  363.     'ng',
  364.     'ni',
  365.     'nl',
  366.     'no',
  367.     'np',
  368.     'nr',
  369.     'nu',
  370.     'nz',
  371.     'om',
  372.     'pa',
  373.     'pe',
  374.     'pf',
  375.     'pg',
  376.     'ph',
  377.     'pk',
  378.     'pl',
  379.     'pm',
  380.     'pn',
  381.     'pr',
  382.     'ps',
  383.     'pt',
  384.     'pw',
  385.     'py',
  386.     'qa',
  387.     're',
  388.     'ro',
  389.     'rs',
  390.     'ru',
  391.     'rw',
  392.     'sa',
  393.     'sb',
  394.     'sc',
  395.     'sd',
  396.     'se',
  397.     'sg',
  398.     'sh',
  399.     'si',
  400.     'sj',
  401.     'sk',
  402.     'sl',
  403.     'sm',
  404.     'sn',
  405.     'so',
  406.     'sr',
  407.     'st',
  408.     'su',
  409.     'sv',
  410.     'sy',
  411.     'sz',
  412.     'tc',
  413.     'td',
  414.     'tf',
  415.     'tg',
  416.     'th',
  417.     'tj',
  418.     'tk',
  419.     'tl',
  420.     'tm',
  421.     'tn',
  422.     'to',
  423.     'tp',
  424.     'tr',
  425.     'tt',
  426.     'tv',
  427.     'tw',
  428.     'tz',
  429.     'ua',
  430.     'ug',
  431.     'uk',
  432.     'um',
  433.     'us',
  434.     'uy',
  435.     'uz',
  436.     'va',
  437.     'vc',
  438.     've',
  439.     'vg',
  440.     'vi',
  441.     'vn',
  442.     'vu',
  443.     'wf',
  444.     'ws',
  445.     'ye',
  446.     'yt',
  447.     'yu',
  448.     'za',
  449.     'zm',
  450.     'zw']
  451. domains = '(?:%s)' % '|'.join(TLDs)
  452. email_regex_string = '(([a-zA-Z0-9_][a-zA-Z0-9_\\-\\.]*)(\\+[a-zA-Z0-9_\\-\\.]+)?@(([a-zA-Z0-9\\-_]+\\.?)*[a-zA-Z]{1,4}))'
  453. email_regex = re.compile(email_regex_string)
  454. email_wholestring_regex = re.compile('^' + email_regex_string + '$')
  455. is_email = primitives.ischeck((lambda s: bool(email_wholestring_regex.match(s))))
  456.  
  457. class EmailAddress(tuple):
  458.     
  459.     def __new__(cls, addr, default_domain = sentinel):
  460.         
  461.         try:
  462.             (name, label, domain) = parse_email(addr)
  463.         except:
  464.             if default_domain is sentinel:
  465.                 raise 
  466.             else:
  467.                 (name, label, domain) = parse_email(addr + '@' + default_domain)
  468.  
  469.         return tuple.__new__(cls, (name, label, domain))
  470.  
  471.     
  472.     def name(self):
  473.         return self[0]
  474.  
  475.     name = property(name)
  476.     
  477.     def label(self):
  478.         return self[1]
  479.  
  480.     label = property(label)
  481.     
  482.     def domain(self):
  483.         return self[2]
  484.  
  485.     domain = property(domain)
  486.     
  487.     def __str__(self):
  488.         if self.label:
  489.             return '%s+%s@%s' % self
  490.         else:
  491.             return '%s@%s' % (self.name, self.domain)
  492.  
  493.     
  494.     def __repr__(self):
  495.         return '<EmailAddress %s>' % (self,)
  496.  
  497.  
  498.  
  499. def parse_email(s):
  500.     match = email_wholestring_regex.match(s)
  501.     (wholething, user, lbl, dom, __) = match.groups()
  502.     if lbl:
  503.         lbl = lbl.strip('+')
  504.     else:
  505.         lbl = ''
  506.     return (user, lbl, dom)
  507.  
  508. protocols = 'ftp|https?|gopher|msnim|icq|telnet|nntp|aim|file|svn|svn+(?:\\w)+'
  509. linkify_url_pattern = re.compile('(?=[a-zA-Z0-9])                          # Must start correctly\n      ((?:                                        # Match the leading part (proto://hostname, or just hostname)\n          (?P<protocol>\n          (?:%s)                                  #     protocol\n          ://                                     #     ://\n          (?:                                     #     Optional \'username:password@\'\n              \\w+                                 #         username\n              (?::\\w+)?                           #         optional :password\n              @                                   #         @\n          )?)?                                    #\n          (?P<hostname>[-\\w]+(?:\\.\\w[-\\w]*)*)     #     hostname (sub.example.com)\n      )?                                          #\n      (?::\\d+)?                                   # Optional port number\n      (?:                                         # Rest of the URL, optional\n          /?                                      #     Start with \'/\'\n          [^.!,?;:"<>\\[\\]{}\\s\\x7F-\\xFF]*          #     Can\'t start with these\n          (?:                                     #\n              [.!,?;:]+                           #     One or more of these\n              [^.!,?;:"<>\\[\\]{}\\s\\x7F-\\xFF]+      #     Can\'t finish with these\n              #\'"                                 #     # or \' or "\n          )*                                      #\n      )?)                                         #\n   ' % protocols, re.VERBOSE)
  510.  
  511. def isurl(text):
  512.     m = linkify_url_pattern.match(text)
  513.     if not m:
  514.         return False
  515.     
  516.     protocol = m.group('protocol')
  517.     host = m.group('hostname')
  518.     if host is not None:
  519.         if protocol is None:
  520.             myTLDs = None if '.' in host else [
  521.                 host]
  522.             if len(myTLDs) < 2 or myTLDs[-1] not in TLDs:
  523.                 return False
  524.             
  525.         
  526.     
  527.     return True
  528.  
  529.  
  530. def _dolinkify(text):
  531.     
  532.     def repl(m):
  533.         protocol = m.group('protocol')
  534.         host = m.group('hostname')
  535.         url = m.group()
  536.         after = ''
  537.         if url.endswith(')') and '(' not in url:
  538.             url = url[:-1]
  539.             after = ')'
  540.         
  541.         if host is not None:
  542.             if protocol is None:
  543.                 myTLDs = None if '.' in host else [
  544.                     host]
  545.                 if len(myTLDs) < 2 or myTLDs[-1] not in TLDs:
  546.                     return url + after
  547.                 
  548.             
  549.         
  550.         href = None if protocol is None else url
  551.         return '<a href="%s">%s</a>' % (href, url) + after
  552.  
  553.     text = linkify_url_pattern.sub(repl, text)
  554.     return text
  555.  
  556.  
  557. def linkify(text):
  558.     if not re.search('<.*>', text):
  559.         return _dolinkify(text)
  560.     else:
  561.         lines = []
  562.         for line in re.split('(<.*?>)', text):
  563.             if not re.match('<.*?>', line):
  564.                 line = _dolinkify(line)
  565.             
  566.             lines.append(line)
  567.         
  568.         return ''.join(lines)
  569.  
  570.  
  571. class QueueableMixin(object):
  572.     
  573.     def __init__(self):
  574.         object.__init__(self)
  575.         self._on_queue = False
  576.  
  577.     
  578.     def queue(self):
  579.         if not self._on_queue:
  580.             self._queue()
  581.             self._on_queue = True
  582.         
  583.  
  584.     
  585.     def unqueue(self):
  586.         if self._on_queue:
  587.             self._unqueue()
  588.             self._on_queue = False
  589.         
  590.  
  591.  
  592.  
  593. class ProducerQueuable(QueueableMixin):
  594.     
  595.     def __init__(self, sck):
  596.         QueueableMixin.__init__(self)
  597.         self.sck = sck
  598.  
  599.     
  600.     def _queue(self):
  601.         self.sck.push_with_producer(self)
  602.  
  603.     
  604.     def _unqueue(self):
  605.         
  606.         try:
  607.             self.sck.producer_fifo.remove(self)
  608.         except ValueError:
  609.             pass
  610.  
  611.  
  612.  
  613.  
  614. class RoundRobinProducer(ProducerQueuable):
  615.     
  616.     def __init__(self, sck):
  617.         ProducerQueuable.__init__(self, sck)
  618.         self.list = []
  619.  
  620.     
  621.     def add(self, prod):
  622.         
  623.         try:
  624.             if not callable(prod.more):
  625.                 raise AssertionError('Producers must have a "more" method')
  626.         except:
  627.             traceback.print_exc()
  628.             raise 
  629.  
  630.         self.unqueue()
  631.         self.list.append(prod)
  632.         self.queue()
  633.  
  634.     
  635.     def more(self):
  636.         self._on_queue = True
  637.         d = None
  638.         l = self.list
  639.         prod = None
  640.         while not d and l:
  641.             prod = l.pop(0)
  642.             d = prod.more()
  643.         if d:
  644.             l.append(prod)
  645.         else:
  646.             self.unqueue()
  647.             if self.list:
  648.                 self.queue()
  649.             
  650.         return d
  651.  
  652.  
  653.  
  654. class PriorityProducer(ProducerQueuable):
  655.     
  656.     def __init__(self, sck):
  657.         ProducerQueuable.__init__(self, sck)
  658.         self.high = []
  659.         self.mid = []
  660.         self.low = []
  661.  
  662.     
  663.     def add(self, prod, pri = 'mid'):
  664.         self.unqueue()
  665.         getattr(self, pri).append(prod)
  666.         self.queue()
  667.  
  668.     
  669.     def more(self):
  670.         self._on_queue = True
  671.         d = None
  672.         for l in (self.high, self.mid, self.low):
  673.             if not l:
  674.                 continue
  675.             
  676.             while not d and l:
  677.                 prod = l.pop(0)
  678.                 d = prod.more()
  679.             if d:
  680.                 l.insert(0, prod)
  681.                 break
  682.                 continue
  683.         
  684.         return d
  685.  
  686.  
  687.  
  688. class HTTPConnProgress(HTTPConnection):
  689.     
  690.     def send_file_cb(self, fileobj, progress_cb, blocksize = default_chunksize, progressDelta = 0):
  691.         if self.sock is None:
  692.             if self.auto_open:
  693.                 self.connect()
  694.             else:
  695.                 raise NotConnected()
  696.         
  697.         if self.debuglevel > 0:
  698.             print 'sending contents of', fileobj
  699.         
  700.         
  701.         try:
  702.             read = fileobj.read
  703.             sendall = self.sock.sendall
  704.             chunk = read(blocksize)
  705.             total = 0
  706.             while chunk:
  707.                 total += len(chunk)
  708.                 sendall(chunk)
  709.                 progress_cb(total - progressDelta)
  710.                 chunk = read(blocksize)
  711.         except socket.error:
  712.             v = None
  713.             if v[0] == 32:
  714.                 self.close()
  715.             
  716.             raise 
  717.  
  718.  
  719.  
  720.  
  721. class SocketEventMixin(EventMixin):
  722.     events = EventMixin.events | set(('connected', 'connection_failed', 'socket_error', 'socket_closed'))
  723.     
  724.     def post_connect_error(self, e = None):
  725.         self.event('socket_error')
  726.         self.post_connect_disconnect()
  727.  
  728.     
  729.     def post_connect_expt(self):
  730.         self.event('socket_error')
  731.         self.post_connect_disconnect()
  732.  
  733.     
  734.     def post_connect_disconnect(self):
  735.         self.close()
  736.         self.event('socket_closed')
  737.  
  738.     
  739.     def post_connect_close(self):
  740.         self.close()
  741.         self.event('socket_closed')
  742.  
  743.     
  744.     def reassign(self):
  745.         self.handle_expt = self.post_connect_expt
  746.         self.handle_error = self.post_connect_error
  747.         self.handle_close = self.post_connect_close
  748.         self.do_disconnect = self.post_connect_disconnect
  749.  
  750.  
  751.  
  752. def build_cookie(name, value, version = 0, domain = sentinel, port = sentinel, path = sentinel, secure = False, expires = None, discard = False, comment = None, comment_url = None, rest = {
  753.     'httponly': None }, rfc2109 = False):
  754.     if domain is sentinel:
  755.         domain = None
  756.         domain_specified = False
  757.         domain_initial_dot = False
  758.     else:
  759.         domain_specified = True
  760.         domain_initial_dot = domain.startswith('.')
  761.     if port is sentinel:
  762.         port = None
  763.         port_specified = False
  764.     else:
  765.         port_specified = True
  766.     if path is sentinel:
  767.         path = None
  768.         path_specified = False
  769.     else:
  770.         path_specified = True
  771.     return cookielib.Cookie(**locals())
  772.  
  773.  
  774. def GetSocketType():
  775.     d = GetProxyInfo()
  776.     if d:
  777.         return socks.socksocket
  778.     else:
  779.         return socket.socket
  780.  
  781. NONE = 'NONPROX'
  782. SYSDEFAULT = 'SYSPROX'
  783. CUSTOM = 'SETPROX'
  784.  
  785. def GetProxyInfo():
  786.     ps = proxy_settings
  787.     
  788.     try:
  789.         pd = ps.get_proxy_dict()
  790.     except Exception:
  791.         e = None
  792.         print >>sys.stderr, 'No proxies because: %r' % e
  793.         pd = { }
  794.  
  795.     get = pd.get
  796.     proxytype = get('proxytype')
  797.     port = get('port')
  798.     
  799.     try:
  800.         port = int(port)
  801.     except:
  802.         port = None
  803.  
  804.     addr = get('addr')
  805.     username = get('username')
  806.     password = get('password')
  807.     override = get('override')
  808.     
  809.     try:
  810.         override = int(override)
  811.     except:
  812.         if override not in (SYSDEFAULT, CUSTOM, NONE):
  813.             override = SYSDEFAULT
  814.         
  815.  
  816.     if override:
  817.         override = CUSTOM
  818.     else:
  819.         override = SYSDEFAULT
  820.     if override == NONE:
  821.         return { }
  822.     elif override == SYSDEFAULT:
  823.         px = urllib._getproxies()
  824.         if not px:
  825.             return { }
  826.         
  827.         url = px.get('http', None)
  828.         if url is None:
  829.             return { }
  830.         
  831.         url = urlparse.urlparse(url)
  832.         if not url.hostname:
  833.             pass
  834.         addr = ''
  835.         if not addr:
  836.             return { }
  837.         
  838.         if not url.port:
  839.             pass
  840.         port = 80
  841.         if not url.username and username:
  842.             pass
  843.         username = None
  844.         if not url.password and password:
  845.             pass
  846.         password = None
  847.         proxytype = 'http'
  848.     
  849.     if all((type, port, addr)):
  850.         proxytype = getattr(socks, ('proxy_type_%s' % proxytype).upper(), None)
  851.         return dict(addr = addr, port = port, username = username, password = password, proxytype = proxytype)
  852.     else:
  853.         return { }
  854.  
  855.  
  856. def GetProxyInfoHttp2():
  857.     i = GetProxyInfo()
  858.     if not i:
  859.         return None
  860.     
  861.     return httplib2.ProxyInfo(proxy_type = i['proxytype'], proxy_host = i['addr'], proxy_port = i['port'], proxy_user = i['username'], proxy_pass = i['password'], proxy_rdns = True)
  862.  
  863.  
  864. def getproxies_digsby():
  865.     pinfo = GetProxyInfo()
  866.     proxies = { }
  867.     if pinfo.get('username', None) and pinfo.get('password', None):
  868.         unpw = '%s:%s@' % (pinfo['username'], pinfo['password'])
  869.     else:
  870.         unpw = ''
  871.     if pinfo.get('port', None):
  872.         port = ':' + str(pinfo['port'])
  873.     else:
  874.         port = ''
  875.     host = pinfo.get('addr', None)
  876.     if not host:
  877.         return proxies
  878.     
  879.     all = unpw + host + port
  880.     proxies = urllib.OneProxy()
  881.     proxies._proxyServer = all
  882.     if pinfo['proxytype'] != socks.PROXY_TYPE_HTTP:
  883.         proxy_url = None % 'socks%d://' if pinfo['proxytype'] == socks.PROXY_TYPE_SOCKS4 else 5 + all
  884.         return dict(socks = proxy_url, http = proxy_url, https = proxy_url)
  885.     
  886.     proxies['https'] = 'http://' + all
  887.     proxies['http'] = 'http://' + all
  888.     proxies['ftp'] = 'http://' + all
  889.     return proxies
  890.  
  891.  
  892. class SocksProxyHandler(urllib2.ProxyHandler):
  893.     handler_order = 100
  894.     
  895.     def proxy_open(self, req, type):
  896.         
  897.         try:
  898.             req._proxied
  899.         except AttributeError:
  900.             proxyinfo = self.proxies.get(type, '')
  901.             proxytype = urllib2._parse_proxy(proxyinfo)[0]
  902.             if proxytype is None:
  903.                 req._proxied = False
  904.                 return urllib2.ProxyHandler.proxy_open(self, req, type)
  905.             else:
  906.                 req._proxytype = proxytype
  907.                 req._proxied = True
  908.                 if proxytype == 'http' and type != 'https':
  909.                     return urllib2.ProxyHandler.proxy_open(self, req, type)
  910.                 else:
  911.                     return None
  912.         except:
  913.             proxytype is None
  914.  
  915.         return None
  916.  
  917.     
  918.     def socks4_open(self, req):
  919.         return self.socks_open(req, 4)
  920.  
  921.     
  922.     def socks5_open(self, req):
  923.         return self.socks_open(req, 5)
  924.  
  925.     
  926.     def socks_open(self, req, sockstype):
  927.         (orig_url_type, __, __, orighostport) = urllib2._parse_proxy(req.get_full_url())
  928.         req.set_proxy(orighostport, orig_url_type)
  929.         endpoint = req.get_host()
  930.         if ':' in endpoint:
  931.             (host, port) = endpoint.rsplit(':', 1)
  932.             port = int(port)
  933.         else:
  934.             host = endpoint
  935.             port = 80
  936.         req._proxied = True
  937.         return self.parent.open(req)
  938.  
  939.  
  940. if hasattr(httplib, 'HTTPS'):
  941.     
  942.     class SocksHttpsOpener(urllib2.HTTPSHandler):
  943.         handler_order = 101
  944.         
  945.         def https_open(self, req):
  946.             if getattr(req, '_proxied', False) and getattr(req, '_proxytype', None) is not None:
  947.                 return urllib2.HTTPSHandler.do_open(self, SocksHttpsConnection, req)
  948.             else:
  949.                 return urllib2.HTTPSHandler.https_open(self, req)
  950.  
  951.  
  952.     
  953.     class SocksHttpsConnection(httplib.HTTPSConnection):
  954.         _sockettype = socks.socksocket
  955.         
  956.         def connect(self):
  957.             pd = urllib.getproxies().get('https', None)
  958.             if pd is None:
  959.                 sockstype = ''
  960.             else:
  961.                 (sockstype, user, password, hostport) = urllib2._parse_proxy(pd)
  962.             (host, port) = hostport.rsplit(':', 1)
  963.             port = int(port)
  964.             sock = self._sockettype(socket.AF_INET, socket.SOCK_STREAM)
  965.             sock.setproxy(proxytype = getattr(socks, 'PROXY_TYPE_%s' % sockstype.upper()), addr = host, port = port, rdns = True, username = user, password = password)
  966.             sock.connect((self.host, self.port))
  967.             ssl = socket.ssl(sock, self.key_file, self.cert_file)
  968.             self.sock = httplib.FakeSocket(sock, ssl)
  969.  
  970.  
  971.  
  972.  
  973. class SocksHttpOpener(urllib2.HTTPHandler):
  974.     handler_order = 101
  975.     
  976.     def http_open(self, req):
  977.         proxytype = getattr(req, '_proxytype', None)
  978.         if getattr(req, '_proxied', False) and proxytype not in ('http', None):
  979.             return urllib2.HTTPHandler.do_open(self, SocksConnection, req)
  980.         else:
  981.             return urllib2.HTTPHandler.http_open(self, req)
  982.  
  983.  
  984.  
  985. class SocksConnection(httplib.HTTPConnection):
  986.     _sockettype = socks.socksocket
  987.     
  988.     def connect(self):
  989.         pd = urllib.getproxies().get('http', None)
  990.         if pd is None:
  991.             sockstype = ''
  992.         else:
  993.             (sockstype, user, password, hostport) = urllib2._parse_proxy(pd)
  994.         if 'socks' not in sockstype:
  995.             return httplib.HTTPConnection.connect(self)
  996.         
  997.         (host, port) = hostport.rsplit(':', 1)
  998.         port = int(port)
  999.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  1000.             (af, socktype, proto, canonname, sa) = res
  1001.             
  1002.             try:
  1003.                 self.sock = self._sockettype(af, socktype, proto)
  1004.                 self.sock.setproxy(proxytype = getattr(socks, 'PROXY_TYPE_%s' % sockstype.upper()), addr = host, port = port, rdns = False, username = user, password = password)
  1005.                 if self.debuglevel > 0:
  1006.                     print 'connect: (%s, %s)' % (self.host, self.port)
  1007.                 
  1008.                 self.sock.connect(sa)
  1009.             except socket.error:
  1010.                 msg = None
  1011.                 if self.debuglevel > 0:
  1012.                     print 'connect fail:', (self.host, self.port)
  1013.                 
  1014.                 if self.sock:
  1015.                     self.sock.close()
  1016.                 
  1017.                 self.sock = None
  1018.                 continue
  1019.  
  1020.             break
  1021.         
  1022.         if not self.sock:
  1023.             raise socket.error, msg
  1024.         
  1025.  
  1026.  
  1027.  
  1028. class DigsbyHttpProxyPasswordManager(urllib2.HTTPPasswordMgr):
  1029.     
  1030.     def find_user_password(self, realm, uri):
  1031.         pi = GetProxyInfo()
  1032.         return (None, None if not pi['username'] else None)
  1033.  
  1034.  
  1035. if not hasattr(urllib, '_getproxies'):
  1036.     urllib._getproxies = urllib.getproxies
  1037.     urllib.getproxies = getproxies_digsby
  1038.     urllib2.UnknownHandler.handler_order = sys.maxint
  1039.     urllib2.ProxyDigestAuthHandler.__bases__ = urllib2.ProxyDigestAuthHandler.__bases__[::-1]
  1040.     urllib2.ProxyBasicAuthHandler.handler_order = 499
  1041.     httplib2.ProxyInfo.get_default_proxy = staticmethod(GetProxyInfoHttp2)
  1042.  
  1043.  
  1044. def GetDefaultHandlers():
  1045.     handlers = [
  1046.         SocksProxyHandler,
  1047.         SocksHttpOpener]
  1048.     httpsopener = globals().get('SocksHttpsOpener', None)
  1049.     if httpsopener is not None:
  1050.         handlers.append(httpsopener)
  1051.     
  1052.     pwdmgr = DigsbyHttpProxyPasswordManager()
  1053.     for auth_handler_type in (urllib2.ProxyBasicAuthHandler, urllib2.ProxyDigestAuthHandler):
  1054.         handlers.append(auth_handler_type(pwdmgr))
  1055.     
  1056.     return handlers
  1057.  
  1058.  
  1059. def build_opener(*a, **k):
  1060.     if 'default_classes' not in k:
  1061.         k['default_classes'] = GetDefaultHandlers()
  1062.     
  1063.     return urllib2.build_opener(*a, **k)
  1064.  
  1065. opener = urllib2.build_opener(*GetDefaultHandlers())
  1066. urllib2.install_opener(opener)
  1067. _hostprog = re.compile('^//([^/?]*)(.*)$')
  1068.  
  1069. def splithost(url):
  1070.     match = _hostprog.match(url)
  1071.     if match:
  1072.         groups = match.group(1, 2)
  1073.         if groups[0] == '':
  1074.             return (groups[0], '/' + groups[1])
  1075.         else:
  1076.             return groups
  1077.     
  1078.     return (None, url)
  1079.  
  1080. urllib.splithost = urllib2.splithost = splithost
  1081.  
  1082. def httpok(_code):
  1083.     return getattr(_code, 'status', _code) // 100 == 2
  1084.  
  1085.  
  1086. class CallbackProducerMixin(object):
  1087.     
  1088.     def __init__(self):
  1089.         bases = self.__class__.__bases__
  1090.         found_self = False
  1091.         self._siblingClass = None
  1092.         for base in bases:
  1093.             if base is CallbackProducerMixin:
  1094.                 found_self = True
  1095.                 continue
  1096.             if hasattr(base, 'more') and found_self:
  1097.                 self._siblingClass = base
  1098.                 break
  1099.                 continue
  1100.         
  1101.         if self._siblingClass is None:
  1102.             raise AssertionError("This mix-in requires there is a sibling class with a 'more' method. Additionally, CallbackProducerMixin must be *before* that class in the inheritance list (for method resolution reasons).")
  1103.         
  1104.  
  1105.     
  1106.     def set_callback(self, callback = None):
  1107.         self._callback = callback
  1108.  
  1109.     set_callback = callsback(set_callback)
  1110.     
  1111.     def more(self):
  1112.         if not hasattr(self, '_siblingClass'):
  1113.             result = ''
  1114.         else:
  1115.             result = self._siblingClass.more(self)
  1116.         if result == '':
  1117.             if getattr(self, '_callback', None) is not None:
  1118.                 self._callback.success()
  1119.             
  1120.             if getattr(self, '_callback', None) is not None:
  1121.                 del self._callback
  1122.             
  1123.         
  1124.         return result
  1125.  
  1126.  
  1127.  
  1128. class SimpleCallbackProducer(CallbackProducerMixin, asynchat.simple_producer):
  1129.     
  1130.     def __init__(self, data):
  1131.         asynchat.simple_producer.__init__(self, data)
  1132.         CallbackProducerMixin.__init__(self)
  1133.  
  1134.  
  1135.  
  1136. def _fifo_remove(self, val):
  1137.     
  1138.     try:
  1139.         self.list.remove(val)
  1140.     except Exception:
  1141.         return False
  1142.  
  1143.     return True
  1144.  
  1145. asynchat.fifo.remove = _fifo_remove
  1146.  
  1147. def producer_cb(data, callback = None):
  1148.     prod = SimpleCallbackProducer(data)
  1149.     prod.set_callback(callback = callback)
  1150.     return prod
  1151.  
  1152. producer_cb = callsback(producer_cb)
  1153.  
  1154. def get_snurl(url):
  1155.     return get_short_url(url, 'snurl')
  1156.  
  1157.  
  1158. def get_isgd(url):
  1159.     return get_short_url(url, 'isgd')
  1160.  
  1161.  
  1162. def get_tinyurl(url):
  1163.     return get_short_url(url, 'tinyurl')
  1164.  
  1165.  
  1166. class UrlShortener(object):
  1167.     endpoint = None
  1168.     
  1169.     def shorten(self, url):
  1170.         
  1171.         try:
  1172.             resp = urllib2.urlopen(UrlQuery(self.endpoint, d = self.get_args(url.encode('utf-8'))))
  1173.         except urllib2.HTTPError:
  1174.             e = None
  1175.             resp = e
  1176.  
  1177.         return self.process_response(resp)
  1178.  
  1179.     
  1180.     def get_args(self, url):
  1181.         raise NotImplementedError
  1182.  
  1183.     
  1184.     def process_response(self, resp):
  1185.         if resp.code != 200:
  1186.             body = resp.read()
  1187.             raise Exception(body)
  1188.         
  1189.         ret = resp.read()
  1190.         return ret
  1191.  
  1192.  
  1193.  
  1194. class isgd_shortener(UrlShortener):
  1195.     endpoint = 'http://is.gd/api.php'
  1196.     
  1197.     def get_args(self, url):
  1198.         return dict(longurl = url)
  1199.  
  1200.  
  1201.  
  1202. class tinyurl_shortener(UrlShortener):
  1203.     endpoint = 'http://tinyurl.com/api-create.php'
  1204.     
  1205.     def get_args(self, url):
  1206.         return dict(url = url)
  1207.  
  1208.  
  1209.  
  1210. class snipr_shortener(UrlShortener):
  1211.     endpoint = 'http://snipr.com/site/snip'
  1212.     
  1213.     def get_args(self, url):
  1214.         return dict(r = 'simple', link = url.encode('url'))
  1215.  
  1216.     
  1217.     def process_response(self, resp):
  1218.         ret = UrlShortener.process_response(self, resp)
  1219.         if not ret.startswith('http'):
  1220.             raise Exception('bad url', ret)
  1221.         
  1222.         return ret
  1223.  
  1224.  
  1225. _shorteners = {
  1226.     'snipr': snipr_shortener,
  1227.     'snurl': snipr_shortener,
  1228.     'snipurl': snipr_shortener,
  1229.     'isgd': isgd_shortener,
  1230.     'tinyurl': tinyurl_shortener,
  1231.     'tiny': tinyurl_shortener }
  1232.  
  1233. def get_short_url(url, provider = 'snipr'):
  1234.     shortener = _shorteners.get(provider)
  1235.     if shortener is None:
  1236.         raise Exception('UrlShortener provider %r not found', provider)
  1237.     
  1238.     return shortener().shorten(url)
  1239.  
  1240. if __name__ == '__main__':
  1241.     print get_snurl('http://www.google.com')
  1242.  
  1243.